static int waypt_out_count;
static route_head* csv_track, *csv_route;
-static double utm_northing, utm_easting, utm_zone = 0;
-static char utm_zonec;
-static UrlLink* link_;
-static gpsbabel_optional::optional<bool> lat_dir_positive;
-static gpsbabel_optional::optional<bool> lon_dir_positive;
+
+struct xcsv_parse_data {
+ QString rte_name;
+ QString trk_name;
+ bool new_track{false};
+ double utm_northing{0};
+ double utm_easting{0};
+ double utm_zone{0};
+ char utm_zonec{'N'};
+ UrlLink* link_{nullptr};
+ gpsbabel_optional::optional<bool> lat_dir_positive;
+ gpsbabel_optional::optional<bool> lon_dir_positive;
+};
#endif // CSVFMTS_ENABLED
/* xcsv_parse_val() - parse incoming data into the waypt structure. */
/* usage: xcsv_parse_val("-123.34", *waypt, *field_map) */
/*****************************************************************************/
-static void
+static void
xcsv_parse_val(const char* s, Waypoint* wpt, const field_map& fmp,
- route_head** trk, const int line_no)
+ xcsv_parse_data* parse_data, const int line_no)
{
const char* enclosure = "";
geocache_data* gc_data = nullptr;
wpt->notes = csv_stringtrim(s, "");
break;
case XT_URL:
- if (!link_) {
- link_ = new UrlLink;
+ if (!parse_data->link_) {
+ parse_data->link_ = new UrlLink;
}
- link_->url_ = QString(s).trimmed();
+ parse_data->link_->url_ = QString(s).trimmed();
break;
case XT_URL_LINK_TEXT:
- if (!link_) {
- link_ = new UrlLink;
+ if (!parse_data->link_) {
+ parse_data->link_ = new UrlLink;
}
- link_->url_link_text_ = QString(s).trimmed();
+ parse_data->link_->url_link_text_ = QString(s).trimmed();
break;
case XT_ICON_DESCR:
wpt->icon_descr = QString(s).trimmed();
case XT_LAT_DIR:
/* latitude N/S. */
if (*s == 'n' || *s == 'N') {
- lat_dir_positive = true;
+ parse_data->lat_dir_positive = true;
} else if (*s == 's' || *s == 'S') {
- lat_dir_positive = false;
+ parse_data->lat_dir_positive = false;
} else {
warning("parse of string '%s' on line number %d as LAT_DIR failed. Expected 'n', 'N', 's' or 'S'.\n", s, line_no);
}
case XT_LON_DIR:
/* longitude E/W. */
if (*s == 'e' || *s == 'E') {
- lon_dir_positive = true;
+ parse_data->lon_dir_positive = true;
} else if (*s == 'w' || *s == 'W') {
- lon_dir_positive = false;
+ parse_data->lon_dir_positive = false;
} else {
warning("parse of string '%s' on line number %d as LON_DIR failed. Expected 'e', 'E', 'w' or 'W'.\n", s, line_no);
}
&wpt->latitude, &wpt->longitude, MYNAME);
break;
case XT_UTM_ZONE:
- utm_zone = atoi(s);
+ parse_data->utm_zone = atoi(s);
break;
case XT_UTM_ZONEC:
- utm_zonec = s[0];
+ parse_data->utm_zonec = s[0];
break;
case XT_UTM_ZONEF:
- utm_zone = atoi(s);
- utm_zonec = s[strlen(s) - 1];
+ parse_data->utm_zone = atoi(s);
+ parse_data->utm_zonec = s[strlen(s) - 1];
break;
case XT_UTM_EASTING:
- utm_easting = atof(s);
+ parse_data->utm_easting = atof(s);
break;
case XT_UTM_NORTHING:
- utm_northing = atof(s);
+ parse_data->utm_northing = atof(s);
break;
case XT_UTM: {
char* ss;
int i = 0;
- utm_zone = strtod(s, &ss);
- utm_zonec = ss[i];
+ parse_data->utm_zone = strtod(s, &ss);
+ parse_data->utm_zonec = ss[i];
ss++;
- utm_easting = strtod(ss, &ss);
+ parse_data->utm_easting = strtod(ss, &ss);
while (*ss && !isdigit(*ss)) {
ss++;
}
- utm_northing = strtod(ss, nullptr);
+ parse_data->utm_northing = strtod(ss, nullptr);
}
break;
/* ALTITUDE CONVERSIONS ************************************************/
break;
/* Tracks and routes *********************************************/
case XT_ROUTE_NAME:
- if (csv_route) {
- csv_route->rte_name = csv_stringtrim(s, enclosure);
- }
+ parse_data->rte_name = csv_stringtrim(s, enclosure);
break;
case XT_TRACK_NEW:
- if (atoi(s) && csv_track && !QUEUE_EMPTY(&csv_track->Q)) {
- *trk = route_head_alloc();
- csv_track = *trk;
-
- track_add_head(*trk);
- }
+ parse_data->new_track = atoi(s);
break;
case XT_TRACK_NAME:
- if (!csv_track) {
- csv_track = route_head_alloc();
- }
- csv_track->rte_name = csv_stringtrim(s, enclosure);
+ parse_data->trk_name = csv_stringtrim(s, enclosure);
break;
/* OTHER STUFF ***************************************************/
int linecount = 0;
route_head* rte = nullptr;
route_head* trk = nullptr;
- utm_northing = 0;
- utm_easting = 0;
- utm_zone = 0;
- utm_zonec = 'N';
-
- csv_route = csv_track = nullptr;
- if (xcsv_file.datatype == trkdata) {
- csv_track = trk;
- } else if (xcsv_file.datatype == rtedata) {
- csv_route = rte;
- }
while (true) {
QString buff = xcsv_file.stream->readLine();
}
if (!buff.isEmpty()) {
Waypoint* wpt_tmp = new Waypoint;
+ // initialize parse data for accumulation of line results from all fields in this line.
+ xcsv_parse_data parse_data;
// tbuf is a temporary copy of buff since we modify it. :-(
char *tbuf = xstrdup(buff);
const char* s = tbuf;
fatal(MYNAME ": attempt to read, but style '%s' has no IFIELDs in it.\n", CSTR(xcsv_file.description)? CSTR(xcsv_file.description) : "unknown");
}
- lat_dir_positive.reset();
- lon_dir_positive.reset();
int ifield_idx = 0;
/* now rip the line apart, advancing the queue for each tear
*/
while (s) {
const field_map& fmp = xcsv_file.ifields.at(ifield_idx++);
- xcsv_parse_val(s, wpt_tmp, fmp, &trk, linecount);
+ xcsv_parse_val(s, wpt_tmp, fmp, &parse_data, linecount);
if (ifield_idx >= xcsv_file.ifields.size()) {
/* we've wrapped the queue. so stop parsing! */
// If XT_LAT_DIR(XT_LON_DIR) was an input field, and the latitude(longitude) is positive,
// assume the latitude(longitude) was the absolute value and take the sign from XT_LAT_DIR(XT_LON_DIR).
- if (lat_dir_positive.has_value() && !lat_dir_positive.value() && (wpt_tmp->latitude > 0.0)) {
+ if (parse_data.lat_dir_positive.has_value() && !parse_data.lat_dir_positive.value() && (wpt_tmp->latitude > 0.0)) {
wpt_tmp->latitude = -wpt_tmp->latitude;
}
- if (lon_dir_positive.has_value() && !lon_dir_positive.value() && (wpt_tmp->longitude > 0.0)) {
+ if (parse_data.lon_dir_positive.has_value() && !parse_data.lon_dir_positive.value() && (wpt_tmp->longitude > 0.0)) {
wpt_tmp->longitude = -wpt_tmp->longitude;
}
&wpt_tmp->latitude, &wpt_tmp->longitude, &alt, xcsv_file.gps_datum);
}
- if (utm_easting || utm_northing) {
+ if (parse_data.utm_easting || parse_data.utm_northing) {
GPS_Math_UTM_EN_To_Known_Datum(&wpt_tmp->latitude,
&wpt_tmp->longitude,
- utm_easting, utm_northing,
- utm_zone, utm_zonec,
+ parse_data.utm_easting, parse_data.utm_northing,
+ parse_data.utm_zone, parse_data.utm_zonec,
DATUM_WGS84);
}
- if (link_) {
- wpt_tmp->AddUrlLink(*link_);
- delete link_;
- link_ = nullptr;
+ if (parse_data.link_) {
+ wpt_tmp->AddUrlLink(*parse_data.link_);
+ delete parse_data.link_;
+ parse_data.link_ = nullptr;
}
switch (xcsv_file.datatype) {
waypt_add(wpt_tmp);
break;
case trkdata:
- if (trk == nullptr) {
+ if ((trk == nullptr) || parse_data.new_track) {
trk = route_head_alloc();
- csv_track = trk;
track_add_head(trk);
}
+ if (!parse_data.trk_name.isEmpty()) {
+ trk->rte_name = parse_data.trk_name;
+ }
track_add_wpt(trk, wpt_tmp);
break;
case rtedata:
if (rte == nullptr) {
rte = route_head_alloc();
- csv_route = rte;
route_add_head(rte);
}
+ if (!parse_data.rte_name.isEmpty()) {
+ rte->rte_name = parse_data.rte_name;
+ }
route_add_wpt(rte, wpt_tmp);
break;
default:
rm -f ${TMPDIR}/grid-utm~xscv.gpx
gpsbabel -i xcsv,style=${TMPDIR}/testo2.style -f ${REFERENCE}/grid-utm.csv -o gpx -F ${TMPDIR}/grid-utm~xscv.gpx
compare ${REFERENCE}/grid-utm~xscv.gpx ${TMPDIR}/grid-utm~xscv.gpx
+
+# test TRACK_NAME, TRACK_NEW
+echo 'DESCRIPTION track style test 1' >>${TMPDIR}/track1.style
+echo 'EXTENSION csv' >>${TMPDIR}/track1.style
+echo 'FIELD_DELIMITER COMMA' >>${TMPDIR}/track1.style
+echo 'RECORD_DELIMITER NEWLINE' >>${TMPDIR}/track1.style
+echo 'DATATYPE TRACK' >>${TMPDIR}/track1.style
+echo 'IFIELD LON_DECIMAL,"","%f"' >>${TMPDIR}/track1.style
+echo 'IFIELD LAT_DECIMAL,"","%f"' >>${TMPDIR}/track1.style
+echo 'IFIELD TRACK_NAME,"","%s"' >>${TMPDIR}/track1.style
+echo 'IFIELD TRACK_NEW,"","%d"' >>${TMPDIR}/track1.style
+gpsbabel -i xcsv,style=${TMPDIR}/track1.style -f ${REFERENCE}/track/track1.csv -o gpx -F ${TMPDIR}/track1~csv.gpx
+compare ${REFERENCE}/track/track1-2~csv.gpx ${TMPDIR}/track1~csv.gpx
+
+# flip TRACK_NAME, TRACK_NEW order
+echo 'DESCRIPTION track style test 2' >>${TMPDIR}/track2.style
+echo 'EXTENSION csv' >>${TMPDIR}/track2.style
+echo 'FIELD_DELIMITER COMMA' >>${TMPDIR}/track2.style
+echo 'RECORD_DELIMITER NEWLINE' >>${TMPDIR}/track2.style
+echo 'DATATYPE TRACK' >>${TMPDIR}/track2.style
+echo 'IFIELD LON_DECIMAL,"","%f"' >>${TMPDIR}/track2.style
+echo 'IFIELD LAT_DECIMAL,"","%f"' >>${TMPDIR}/track2.style
+echo 'IFIELD TRACK_NEW,"","%d"' >>${TMPDIR}/track2.style
+echo 'IFIELD TRACK_NAME,"","%s"' >>${TMPDIR}/track2.style
+gpsbabel -i xcsv,style=${TMPDIR}/track2.style -f ${REFERENCE}/track/track2.csv -o gpx -F ${TMPDIR}/track2~csv.gpx
+compare ${REFERENCE}/track/track1-2~csv.gpx ${TMPDIR}/track2~csv.gpx
+
+# ROUTE_NAME
+echo 'DESCRIPTION route style test 1' >>${TMPDIR}/route1.style
+echo 'EXTENSION csv' >>${TMPDIR}/route1.style
+echo 'FIELD_DELIMITER COMMA' >>${TMPDIR}/route1.style
+echo 'RECORD_DELIMITER NEWLINE' >>${TMPDIR}/route1.style
+echo 'DATATYPE ROUTE' >>${TMPDIR}/route1.style
+echo 'IFIELD LON_DECIMAL,"","%f"' >>${TMPDIR}/route1.style
+echo 'IFIELD LAT_DECIMAL,"","%f"' >>${TMPDIR}/route1.style
+echo 'IFIELD ROUTE_NAME,"","%s"' >>${TMPDIR}/route1.style
+gpsbabel -i xcsv,style=${TMPDIR}/route1.style -f ${REFERENCE}/route/route1.csv -o gpx -F ${TMPDIR}/route1~csv.gpx
+compare ${REFERENCE}/route/route1~csv.gpx ${TMPDIR}/route1~csv.gpx